package br.com.sgpv2.service.folha;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import br.com.sgpv2.controler.NegocioExeception;
import br.com.sgpv2.entity.folha.Folha;
import br.com.sgpv2.entity.folha.StatusFolhaEnum;
import br.com.sgpv2.entity.movimentacao.Movimentacao;
import br.com.sgpv2.entity.movimentacao.ValoresEvento;
import br.com.sgpv2.hibernate.folha.FolhaRepository;
import br.com.sgpv2.service.movimentacao.MovimentacaoService;

@Service(value = "folhaService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class FolhaServiceImpl implements FolhaService {

	private static final String DD_MM_YYYY = "dd/MM/yyyy";

	private FolhaRepository folhaRepository;
	private MovimentacaoService movimentacaoService;

	@Override
	public void salvar(Folha folha) {
		folhaRepository.salvar(folha);
	}

	@Override
	public void alterar(Folha folha) {
		folhaRepository.alterar(folha);

	}

	@Override
	public List<Folha> listar() {
		return folhaRepository.listar();
	}

	@Override
	public void excluir(Folha folha) {
		folhaRepository.excluir(folha);
	}

	@Override
	public Folha buscar(Integer pk) throws NegocioExeception {

		if (pk == null || pk == 0) {
			throw new NegocioExeception("Folha de pagamento não informada.");
		}

		return folhaRepository.buscar(pk);
	}

	@Autowired
	public void setFolhaRepository(FolhaRepository folhaRepository) {
		this.folhaRepository = folhaRepository;
	}

	public Folha buscarPorMesAno(Integer mes, Integer ano) {
		return folhaRepository.buscarPorMesAno(mes, ano);
	}

	public List<Folha> consultarFolhaFechada() {
		return folhaRepository.consultarFolhaFechada();
	}
	

	public List<Folha> consultarFolhas() {
		return folhaRepository.consultarFolhas();
	}
	

	@Transactional
	public void fecharFolha(Integer mes, Integer ano) {

		Folha folhaFechada = new Folha();
		folhaFechada.setId(folhaRepository.buscarIdPorMesAno(mes, ano));
		folhaFechada.setAno(ano);
		folhaFechada.setMes(mes);
		folhaFechada.setStatus(StatusFolhaEnum.FECHADA);
		folhaRepository.alterar(folhaFechada);

		List<Movimentacao> movimentacoes = folhaRepository.buscarPorMesAno(mes, ano).getMovimentacoes();

		GregorianCalendar calendar = new GregorianCalendar();
		SimpleDateFormat format = new SimpleDateFormat(DD_MM_YYYY);
		try {
			calendar.setTime(format.parse("01/"+mes+"/"+ano));
			calendar.add(GregorianCalendar.MONTH, 1);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Folha folhaExistente = this.folhaRepository.buscarPorMesAno(
				calendar.get(GregorianCalendar.MONTH) + 1,
				calendar.get(GregorianCalendar.YEAR));

		if (folhaExistente == null) {
			copiarFolhaProximoMes(mes, ano, movimentacoes, calendar);
		}

	}

	private void copiarFolhaProximoMes(Integer mes, Integer ano,
			List<Movimentacao> movimentacoes, GregorianCalendar calendar) {
		Folha novaFolha = new Folha();
		
		List<Movimentacao> listaNovasMovimentacoes = new ArrayList<Movimentacao>();

		novaFolha.setAno(calendar.get(GregorianCalendar.YEAR));
		novaFolha.setMes(calendar.get(GregorianCalendar.MONTH) + 1);
		novaFolha.setStatus(StatusFolhaEnum.ABERTA);
		

		for (Movimentacao movimentacao : movimentacoes) {

			Movimentacao movimentacaoNova = new Movimentacao();
			movimentacaoNova.setAno(calendar.get(GregorianCalendar.YEAR));
			movimentacaoNova.setMes(calendar.get(GregorianCalendar.MONTH)+1);
			movimentacaoNova.setContrato(movimentacao.getContrato());
			movimentacaoNova.setData(calendar.getTime());
			movimentacaoNova.setFolha(novaFolha);
			movimentacaoNova.setSalarioBaseMovimentacao(movimentacao
					.getSalarioBaseMovimentacao());
			

			List<ValoresEvento> listaNovosValoresEvento = configurarListaEventos(movimentacao
					.getValoresEvento(),movimentacaoNova);
			movimentacaoNova.setValoresEvento(listaNovosValoresEvento);

			try {
				movimentacaoService
						.calcularValoresTotalMovimentacao(movimentacaoNova);
			} catch (NumberFormatException e) {
			} catch (NegocioExeception e) {
			}

			listaNovasMovimentacoes.add(movimentacaoNova);
		}
		
		novaFolha.setMovimentacoes(listaNovasMovimentacoes);		
		this.folhaRepository.salvar(novaFolha);
	}

	private List<ValoresEvento> configurarListaEventos(
			List<ValoresEvento> valoresEvento, Movimentacao novaMovimentacao) {
		List<ValoresEvento> listaNovosValoresEvento = new ArrayList<ValoresEvento>();
		for (ValoresEvento valor : valoresEvento) {
			
			if (!valor.getEvento().getIsTemporario()) {
				
				ValoresEvento novoValor = new ValoresEvento();
				
				novoValor.setEvento(valor.getEvento());
				novoValor.setValor(valor.getValor());
				novoValor.setValorDescontoFgts(valor.getValorDescontoFgts());
				novoValor.setValorDescontoInss(valor.getValorDescontoInss());
				novoValor.setValorDescontoIrrf(valor.getValorDescontoIrrf());
				novoValor.setValorDescontoSalarioFamilia(valor.getValorDescontoSalarioFamilia());
				novoValor.setMovimentacao(novaMovimentacao);
				
				
				listaNovosValoresEvento.add(novoValor);
			}

		}
		return listaNovosValoresEvento;
	}

	@Autowired
	public void setMovimentacaoService(MovimentacaoService movimentacaoService) {
		this.movimentacaoService = movimentacaoService;
	}

}
